package main

import (
	"dingusxp/trial/test/util"
	"fmt"
	"sync"
)

func main() {

	// TestPanicking()
	TestTrace()
}

func midFunc1() {

	funcName := util.FuncName()
	defer func() {
		if e := recover(); e != nil {
			fmt.Printf("Oh, %s got a panic in process %#V\n", funcName, e)
		}
	}()

	fmt.Printf("call %s\n", util.FuncName())
	panicFunc()
	fmt.Printf("exit %s\n", util.FuncName())
}
func midFunc2() {

	fmt.Printf("call %s\n", util.FuncName())
	panicFunc()
	fmt.Printf("exit %s\n", util.FuncName())
}
func panicFunc() {

	fmt.Printf("call %s\n", util.FuncName())
	if util.True() {
		panic("Oh, my god. I meet a ghost-bug!")
	}
	fmt.Printf("exit %s\n", util.FuncName())
}

// 调用链里一个函数抛出了 panic，则终止当前函数运行并 相当于自身变成了 panic 函数 向上“传染”。
// 特别的：函数开始初始化完成的 defer 函数可以继续运行，并在其中通过 recover 捕获 panic，终止其继续传染。
func TestPanicking() {

	fmt.Printf("call %s\n", util.FuncName())
	fmt.Printf("test1: with recover...\n")
	midFunc1()
	fmt.Printf("test2: without recover...\n")
	midFunc2()
	fmt.Printf("exit %s\n", util.FuncName())
}

func traceFunc1() {

	defer util.Trace()()

	var wg sync.WaitGroup
	wg.Add(1)
	go func() {
		traceFunc2()
		wg.Done()
	}()
	traceFunc3()
	wg.Wait()
}

func traceFunc2() {

	defer util.Trace()()
}
func traceFunc3() {

	defer util.Trace()()
}

func TestTrace() {
	defer util.Trace()()

	traceFunc1()
}
